package ru.zombator.taskman.server.query;

import java.util.List;

import ru.zombator.taskman.core.dbclient.DbException;
import ru.zombator.taskman.core.dbclient.IDbClient;
import ru.zombator.taskman.core.dbclient.impl.DbClientFactory;
import ru.zombator.taskman.core.domain.IManager;
import ru.zombator.taskman.core.domain.IPerson;
import ru.zombator.taskman.core.domain.ITaskProject;
import ru.zombator.taskman.core.domain.IWorker;
import ru.zombator.taskman.core.query.payload.CreateProjectRequest;
import ru.zombator.taskman.core.query.payload.JoinProjectRequest;
import ru.zombator.taskman.core.query.payload.ObjectCreatedResponse;
import ru.zombator.taskman.core.query.payload.ObjectsListedResponse;
import ru.zombator.taskman.core.query.payload.ProjectJoinedResponse;
import ru.zombator.taskman.core.query.payload.ProjectListRequest;
import ru.zombator.taskman.core.query.payload.WhoAmIRequest;
import ru.zombator.taskman.core.query.payload.WhoAmIResponse;
import ru.zombator.taskman.core.query.payload.ProjectListRequest.ShowProjects;

/**
 * Фабрика, создающая объекты {@link LocalResponder}, отвечающие на запросы
 * конкретного пользователя.
 * 
 * @author nvamelichev
 * 
 */
public class ResponderFactory {
	private static IDbClient dbClient() {
		return DbClientFactory.newDbClient();
	}

	/**
	 * Создать новый responder для ответа на вопрос "кто я"
	 * 
	 * @param ipAddress
	 *            - IP-адрес вызывающего
	 * @return responder
	 */
	public static LocalResponder newResponderForWhoAmI(final String ipAddress) {
		LocalResponder resp = new LocalResponder();
		resp.setHandler(WhoAmIRequest.class, new IRequestHandler() {
			@Override
			public Object getResponse(Object req, Logger log)
					throws DbException {
				log.log("Получение информации о пользователе с IP-адресом %s.",
						ipAddress);
				IPerson who = dbClient().getUser(ipAddress);
				String rank = who instanceof IManager ? "менеджер"
						: "исполнитель";
				if (who != null) {
					log.log("Обнаружен %s %s [%s], UID %s.", rank, who
							.getName(), ipAddress, who.getId().toString());
				} else {
					log.log("Пользователя с IP-адресом %s не обнаружено.",
							ipAddress);
				}
				return new WhoAmIResponse(who);
			}
		});
		return resp;
	}

	/**
	 * Создать новый responder, отвечающий на запросы, которые делают
	 * менеджеры.
	 * 
	 * @param manager
	 *            - менеджер
	 * @return responder
	 */	
	private static LocalResponder newResponderForManager(final IManager manager) {
		LocalResponder responder = new LocalResponder();
		responder.setHandler(CreateProjectRequest.class, new IRequestHandler() {
			@Override
			public Object getResponse(Object req, Logger log)
					throws DbException {
				CreateProjectRequest cpr = ((CreateProjectRequest) req);

				log.log("Создание проекта \"%s\" менеджером %s. Пароль: \"%s\"", cpr
						.getName(), manager.getName(), cpr.getPassword());

				ITaskProject project = dbClient().createProject(manager,
						cpr.getName(), cpr.getPassword());
				ObjectCreatedResponse resp = new ObjectCreatedResponse(project);
				
				log.log("Создан проект \"%s\" менеджером %s. UID %s", project
						.getName(), manager.getName(), project.getId().toString());
				
				return resp;
			}
		});
		responder.setHandler(JoinProjectRequest.class, new IRequestHandler() {
			@Override
			public Object getResponse(Object req, Logger log)
					throws DbException {
				JoinProjectRequest jpr = (JoinProjectRequest) req;

				log.log("Присоединение к проекту %s менеджером %s. Пароль %s",
						manager.getName(), jpr.getProject().getName(), jpr
								.getPassword());
				dbClient().joinProject(manager, jpr.getProject(),
						jpr.getPassword());
				return new ProjectJoinedResponse(jpr.getProject());
			}
		});
		responder.setHandler(ProjectListRequest.class, new IRequestHandler() {
            @Override
            public Object getResponse(Object req, Logger log) throws DbException {
                ProjectListRequest plr = (ProjectListRequest) req;
                log.log("Вывод списка %s проектов", plr.whatIsShown().toString());

                List<ITaskProject> projects = null;
                switch (plr.whatIsShown()) {
                case ALL:
                    projects = dbClient().getProjects();
                    break;
                case JOINED:
                    projects = dbClient().getMyProjects(manager);
                    break;
                case NON_JOINED:
                    projects = dbClient().getNonjoinedProjects(manager);
                    break;
                }
                return new ObjectsListedResponse(projects);
            }
        });

		return responder;
	}

	public static LocalResponder newResponder(IPerson forUser) {
		if (forUser instanceof IManager) {
			return newResponderForManager((IManager) forUser);
		} else {
			return newResponderForWorker((IWorker) forUser);
		}
	}

	/**
	 * Создать новый responder, отвечающий на запросы, которые делают
	 * исполнители.
	 * 
	 * @param worker
	 *            - исполнитель
	 * @return responder
	 */		
	private static LocalResponder newResponderForWorker(IWorker forUser) {
		LocalResponder resp = new LocalResponder();
		// TODO handlers
		return resp;
	}
}
